package com.sudoku.ui.content;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;

import javax.swing.JPanel;
import javax.swing.JTextField;

import com.sudoku.common.Constants;
import com.sudoku.common.Utils;
import com.sudoku.listener.InputListener;
import com.sudoku.ui.Sudoku;

public class SPanel extends JPanel {
	private static final long serialVersionUID = -759448781363103273L;
	

	private int[][] puzzle = new int[Constants.GRID_SIZE][Constants.GRID_SIZE];
	private boolean[][] mask = new boolean[Constants.GRID_SIZE][Constants.GRID_SIZE];
	private int level;
	private int totalBlankCnt;
	private int filledCellCnt;
	private JPanel gridPanel;
	private Sudoku sudoku;
	private SStatus status;
	private JTextField[][] tfCells = new JTextField[Constants.GRID_SIZE][Constants.GRID_SIZE];
	private InputListener[][] inputListener = new InputListener[Constants.GRID_SIZE][Constants.GRID_SIZE];	
	
	public SPanel(Sudoku sudoku, int difficultLevel) {
		this.setLayout(new BorderLayout());
		this.sudoku = sudoku;
		this.gridPanel = new JPanel(new GridLayout(Constants.GRID_SIZE, Constants.GRID_SIZE));
		this.puzzle = Utils.generateSukodu();
		this.mask = Utils.generateMask(difficultLevel);
		this.totalBlankCnt = Utils.getTrueCnt(mask);
		this.filledCellCnt = 0;
		this.level = difficultLevel;
		
		for (int row = 0; row < Constants.GRID_SIZE; row++) {
			for (int col = 0; col < Constants.GRID_SIZE; col++) {
				tfCells[row][col] = new JTextField();
				this.gridPanel.add(tfCells[row][col]);
				
				if (mask[row][col]) {
					tfCells[row][col].setText("");
					tfCells[row][col].setEditable(true);
					tfCells[row][col].setBackground(Constants.OPEN_CELL_BGCOLOR);
					
					inputListener[row][col] = new InputListener(sudoku, this, tfCells[row][col], row, col);
					tfCells[row][col].getDocument().addDocumentListener(inputListener[row][col]);
				} else {
					tfCells[row][col].setText(puzzle[row][col] + "");
					tfCells[row][col].setEditable(false);
					tfCells[row][col].setBackground(Constants.CLOSED_CELL_BGCOLOR);
					tfCells[row][col].setForeground(Constants.CLOSED_CELL_TEXT);
				}
				
				// 美化单元格
				tfCells[row][col].setHorizontalAlignment(JTextField.CENTER);
				tfCells[row][col].setFont(Constants.FONT_NUMBERS);
			}
		}
		
		this.gridPanel.setPreferredSize(new Dimension(Constants.CANVAS_WIDTH, Constants.CANVAS_HEIGHT));
		this.add(gridPanel, BorderLayout.CENTER);
		
		/**
		 * 需要在单元格初始化结束后再添加信息栏
		 */
		this.status = new SStatus(this);
		this.add(status, BorderLayout.SOUTH);
	}

	public SPanel(Sudoku sudoku, int difficultLevel, String[][] jTextFields, int[][] puzzle, boolean[][] mask) {
		this.setLayout(new BorderLayout());
		this.sudoku = sudoku;
		this.gridPanel = new JPanel(new GridLayout(Constants.GRID_SIZE, Constants.GRID_SIZE));
		this.puzzle = puzzle;
		this.mask = mask;
		this.totalBlankCnt = Utils.getTrueCnt(mask);
		
		this.level = difficultLevel;
		
		for (int row = 0; row < Constants.GRID_SIZE; row++) {
			for (int col = 0; col < Constants.GRID_SIZE; col++) {
				tfCells[row][col] = new JTextField();
				this.gridPanel.add(tfCells[row][col]);
				
				if (mask[row][col]) {
					tfCells[row][col].setText(jTextFields[row][col]);
					tfCells[row][col].setEditable(true);
					
					if (jTextFields==null || "".equals(jTextFields[row][col])) {
						tfCells[row][col].setBackground(Constants.OPEN_CELL_BGCOLOR);
					} else {
						if (Utils.isInteger(jTextFields[row][col]) && Integer.parseInt(jTextFields[row][col])==puzzle[row][col]) {
							tfCells[row][col].setBackground(Color.GREEN);
						} else {
							tfCells[row][col].setBackground(Color.RED);
						}
					}
					
					inputListener[row][col] = new InputListener(sudoku, this, tfCells[row][col], row, col);
					tfCells[row][col].getDocument().addDocumentListener(inputListener[row][col]);
				} else {
					tfCells[row][col].setText(puzzle[row][col] + "");
					tfCells[row][col].setEditable(false);
					tfCells[row][col].setBackground(Constants.CLOSED_CELL_BGCOLOR);
					tfCells[row][col].setForeground(Constants.CLOSED_CELL_TEXT);
				}
				
				tfCells[row][col].setHorizontalAlignment(JTextField.CENTER);
				tfCells[row][col].setFont(Constants.FONT_NUMBERS);
			}
		}
		
		this.gridPanel.setPreferredSize(new Dimension(Constants.CANVAS_WIDTH, Constants.CANVAS_HEIGHT));
		this.add(gridPanel, BorderLayout.CENTER);
		
		/**
		 * 需要再单元格初始化结束后重置“已填充的单元格数量”
		 */
		this.setFilledCellCnt();
		this.status = new SStatus(this);
		this.add(status, BorderLayout.SOUTH);
	}

	public boolean isGemeOver() {
		boolean result = true;

		check:
		for (int row = 0; row<Constants.GRID_SIZE; row++) {
			for (int col = 0; col<Constants.GRID_SIZE; col++) {
				String text = tfCells[row][col].getText();
				if (!Utils.isInteger(text) || Integer.parseInt(text)!=puzzle[row][col]) {
					result = false;
					break check;
				}
			}
		}
		
		return result;
	}
	/**
	 * Getters and Setters
	 */
	public JTextField[][] getTfCells() {
		return tfCells;
	}

	public void setTfCells(JTextField[][] tfCells) {
		this.tfCells = tfCells;
	}

	public int[][] getPuzzle() {
		return puzzle;
	}

	public void setPuzzle(int[][] puzzle) {
		this.puzzle = puzzle;
	}

	public boolean[][] getMask() {
		return mask;
	}

	public void setMask(boolean[][] mask) {
		this.mask = mask;
	}

	public int getLevel() {
		return level;
	}

	public void setLevel(int difficultLevel) {
		this.level = difficultLevel;
	}

	public InputListener[][] getInputListener() {
		return inputListener;
	}

	public void setInputListener(InputListener[][] inputListener) {
		this.inputListener = inputListener;
	}

	
	
	public int getTotalBlankCnt() {
		return totalBlankCnt;
	}

	public void setTotalBlankCnt(int totalBlankCnt) {
		this.totalBlankCnt = totalBlankCnt;
	}

	public int getFilledCellCnt() {
		return filledCellCnt;
	}

	public void setFilledCellCnt() {
		int cnt = 0;
		for (int row = 0; row < Constants.GRID_SIZE; row++) {
			for (int col = 0; col < Constants.GRID_SIZE; col++) {
				String text = tfCells[row][col].getText();
				if (mask[row][col] && text!=null && !"".equals(text)) {
					cnt++;
				}
			}
		}
		filledCellCnt = cnt;
	}

	public SStatus getStatus() {
		return status;
	}

	public void setStatus(SStatus status) {
		this.status = status;
	}
}
